package com.wzapp.sitposture.common.util;

import com.wzapp.sitposture.common.error.ErrorMessage;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.security.authentication.BadCredentialsException;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.oauth2.common.exceptions.InvalidGrantException;
import org.springframework.security.oauth2.common.exceptions.InvalidTokenException;
import org.springframework.security.oauth2.common.exceptions.OAuth2Exception;
import org.springframework.stereotype.Component;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServletResponse;

/**
 * 功能: 自定义异常解析<br/>
 *
 * @author ql
 * @version 0.4
 * @create 2018-07-02 11:10
 **/
@Component
public class ExceptionUtil {

    @Autowired
    private ResourceBundleUtil resourceBundleUtil;

    /**
     * 功能:自定义异常 <br/>
     *
     * @param response
     * @param authException
     * @return void
     * @author ql
     * @create 2018-07-02 11:17
     **/
    public void returnEigException(HttpServletResponse response, AuthenticationException authException) throws ServletException {
        ErrorMessage errorMessage = getErrorMessage(authException);

        response.setContentType("application/json");
        response.setStatus(HttpServletResponse.SC_UNAUTHORIZED);
        try {
            ObjectMapper mapper = new ObjectMapper();
            mapper.writeValue(response.getOutputStream(), errorMessage);
        } catch (Exception e) {
            throw new ServletException("parse oatuhexception error");
        }
    }

    /**
     * 功能: 自定义返回异常信息<br/>
     *
     * @param authException
     * @return ErrorMessage
     * @author ql
     * @create 2018-07-02 18:07
     **/
    private ErrorMessage getErrorMessage(Throwable authException) {

        Throwable throwable = obtainThrowable(authException);
        ErrorMessage errorMessage = new ErrorMessage();
        errorMessage.setCode(401);
        errorMessage.setMessage(throwable.getMessage());
        if (throwable instanceof InvalidTokenException) {
            errorMessage = resourceBundleUtil.parseErrorMessage("authentication.token.access_token.error", new String[]{});
            if (throwable.getMessage().contains("Invalid refresh token (expired):")) {
                errorMessage = resourceBundleUtil.parseErrorMessage("authentication.token.refresh_token.error", new String[]{});
            }
        }
        if (throwable instanceof InvalidGrantException) {
            errorMessage = resourceBundleUtil.parseErrorMessage("authentication.token.refresh_token.error", new String[]{});
        }

        if (throwable instanceof BadCredentialsException) {
            errorMessage = resourceBundleUtil.parseErrorMessage("userCenter.user.token.error", new String[]{});
        }
        return errorMessage;
    }

    public ResponseEntity returnEigResponseEntity(Exception e, ResponseEntity responseEntity) throws Exception {

        Object body = responseEntity.getBody();
        if (!(body instanceof OAuth2Exception)) {
            return responseEntity;
        }

        OAuth2Exception oAuth2Exception = (OAuth2Exception) body;
        ErrorMessage errorMessage = getErrorMessage(oAuth2Exception);

        HttpHeaders headers = new HttpHeaders();
        headers.setAll(responseEntity.getHeaders().toSingleValueMap());
        //
        return new ResponseEntity(errorMessage, headers, HttpStatus.UNAUTHORIZED);
    }

    public Throwable obtainThrowable(Throwable ex) {

        Throwable throwable = ex;
        while (throwable != null) {
            if (null == throwable.getCause()) {
                break;
            }
            throwable = throwable.getCause();
        }
        return throwable;
    }
}
